package work.mediway.mdm.biz.service.patient.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mediway.hos.common.utils.spring.SpringUtils;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import work.mediway.mdm.core.mapper.CommonMapper;
import work.mediway.mdm.core.page.QueryRequest;
import work.mediway.mdm.core.thread.DimplesTaskExecutor;
import work.mediway.mdm.biz.dto.patient.PatientDTO;
import work.mediway.mdm.biz.entity.patient.PaPatient;
import work.mediway.mdm.biz.mapper.patient.PaPatientMapper;
import work.mediway.mdm.biz.vo.patient.PatientDetailVO;
import work.mediway.mdm.biz.vo.patient.PatientListVO;
import work.mediway.mdm.biz.vo.patient.StatisticsPatientNumVO;
import work.mediway.mdm.core.constant.MdmConstant;
import work.mediway.mdm.core.exception.BizException;
import work.mediway.mdm.core.exception.DataException;
import work.mediway.mdm.biz.service.patient.PaPatientService;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2020/12/11
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@Service
public class PaPatientServiceImpl extends ServiceImpl<PaPatientMapper, PaPatient> implements PaPatientService {

    @Override
    public List<Map<String, String>> statisticsNumGroupByDay(String startDate, String endDate) {
        return this.baseMapper.statisticsNumGroupByDay(startDate, endDate);
    }

    @Override
    public Map<String, Object> statisticsNumAge() {
        Map<String, Object> result = MapUtil.newHashMap();
        // 数据完整的患者年龄统计，目前区分是否完整的标准是患者是否存在身份证号
        List<Callable<List<StatisticsPatientNumVO>>> task = CollUtil.newArrayList();
        task.add(() -> {
            PaPatientMapper patientMapper = SpringUtil.getBean(PaPatientMapper.class);
            return patientMapper.statisticsNumAgeComplete();
        });
        task.add(() -> {
            PaPatientMapper patientMapper = SpringUtil.getBean(PaPatientMapper.class);
            return patientMapper.statisticsNumAgeIncomplete();
        });
        // 提交任务
        DimplesTaskExecutor<List<StatisticsPatientNumVO>> taskExecutor = new DimplesTaskExecutor<>("StatisticsPatientAge");
        ExecutorCompletionService<List<StatisticsPatientNumVO>> completionService = taskExecutor.getCompletionService();
        for (Callable<List<StatisticsPatientNumVO>> callable : task) {
            completionService.submit(callable);
        }
        // 获取结果
        for (int i = 0; i < task.size(); i++) {
            try {
                List<StatisticsPatientNumVO> patientNumVos = completionService.take().get();
                if (patientNumVos.get(0).getComplete() == 1) {
                    result.put("complete", patientNumVos);
                } else {
                    result.put("incomplete", patientNumVos);
                }
            } catch (InterruptedException | ExecutionException e) {
                throw new BizException("统计患者年龄分布", e);
            }
        }
        return result;
    }

    @Override
    public StatisticsPatientNumVO statisticsPatient() {
        StatisticsPatientNumVO result = new StatisticsPatientNumVO();
        List<Callable<StatisticsPatientNumVO>> task = CollUtil.newArrayList();
        task.add(() -> this.baseMapper.statisticsPatientTotal());
        task.add(() -> this.baseMapper.statisticsMergeTotal());
        task.add(() -> this.baseMapper.statisticsSuspectTotal());
        task.add(() -> this.baseMapper.statisticsInCompleteTotal());
        DimplesTaskExecutor<StatisticsPatientNumVO> taskExecutor = new DimplesTaskExecutor<>("StatisticsPatient");
        ExecutorCompletionService<StatisticsPatientNumVO> completionService = taskExecutor.getCompletionService();
        for (Callable<StatisticsPatientNumVO> callable : task) {
            completionService.submit(callable);
        }
        for (int i = 0, len = task.size(); i < len; i++) {
            try {
                StatisticsPatientNumVO vo = completionService.take().get();
                if (vo.getPatientTotal() != null) {
                    result.setPatientTotal(vo.getPatientTotal());
                }
                if (vo.getMergeTotal() != null) {
                    result.setMergeTotal(vo.getMergeTotal());
                }
                if (vo.getSuspectTotal() != null) {
                    result.setSuspectTotal(vo.getSuspectTotal());
                }
                if (vo.getInCompleteTotal() != null) {
                    result.setInCompleteTotal(vo.getInCompleteTotal());
                }
            } catch (InterruptedException | ExecutionException e) {
                throw new BizException("统计患者总览的数据出错", e);
            }
        }
        return result;
    }

    @Override
    public Page<PatientListVO> pagePatientList(QueryRequest queryRequest, PatientDTO patient) {
        patient.setPatPatientIds(StrUtil.splitTrim(patient.getPatPatientId(), StringPool.PIPE));
        patient.setHosPatientIds(StrUtil.splitTrim(patient.getHosPatientId(), StringPool.PIPE));

        Page<PatientListVO> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        page.setOrders(OrderItem.descs("updateDate DESC"));
        page.setRecords(this.baseMapper.listPatientList(page, patient));

        page.getRecords().forEach(i -> i.setLastUpdateDateTime(StrUtil.join(" ", i.getLastUpdateDate(), i.getLastUpdateTime())));
        return page;
    }

    @Override
    public PatientDetailVO getPatientDetail(String patPatientId, String hosPatientId) {
        if (StrUtil.isBlank(patPatientId) && StrUtil.isBlank(hosPatientId)) {
            throw new DataException("平台Id【patPatientId】和院内Id【hosPatientId】不能同时为空");
        }
        PatientDetailVO detail = this.baseMapper.getPatientDetail(patPatientId, hosPatientId);
        detail.setLastUpdateDateTime(StrUtil.join(" ", detail.getLastUpdateDate(), detail.getLastUpdateTime()));
        return detail;
    }

    @Override
    public String maxPatientId() {
        return this.baseMapper.maxPatientId();
    }

    @Override
    public List<PaPatient> listLaterByPatientId(String btCurrentId) {
        if (StrUtil.isBlank(btCurrentId)) {
            return CollUtil.newArrayList();
        }
        return this.baseMapper.listByPatientId(btCurrentId);
    }

    @Override
    public List<String> patientPath() {
        List<String> query = CollUtil.newArrayList();
        CommonMapper commonMapper = SpringUtils.getBean(CommonMapper.class);
        String sql = "SELECT DISTINCT pai_path FROM " + "pa_account_info";
        List<Map<String, Object>> items = commonMapper.getPublicItems(sql);
        for (Map<String, Object> item : items) {
            Object paiPath = item.get("pai_path");
            if (ObjectUtil.isNotEmpty(paiPath)) {
                query.add(StrUtil.toString(paiPath));
            }
        }
        return query;
    }
}














